package com.hps.demo.serialization;

import io.protostuff.LinkedBuffer;
import io.protostuff.ProtostuffIOUtil;
import io.protostuff.Schema;
import io.protostuff.runtime.RuntimeSchema;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.SerializationException;

/**
 * ProtoStuff序列化工具
 * @author LinkinStar
 */
public class ProtostuffSerializer implements RedisSerializer<Object> {

  private boolean isEmpty(byte[] data) {
    return (data == null || data.length == 0);
  }

  private final Schema<ProtoWrapper> schema;

  private final ProtoWrapper wrapper;

  private final LinkedBuffer buffer;

  public ProtostuffSerializer() {
    this.wrapper = new ProtoWrapper();
    this.schema = RuntimeSchema.getSchema(ProtoWrapper.class);
    this.buffer = LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE);
  }

  @Override
  public byte[] serialize(Object t) throws SerializationException {
    if (t == null) {
      return new byte[0];
    }
    wrapper.data = t;
    try {
      return ProtostuffIOUtil.toByteArray(wrapper, schema, buffer);
    } finally {
      buffer.clear();
    }
  }

  @Override
  public Object deserialize(byte[] bytes) throws SerializationException {
    if (isEmpty(bytes)) {
      return null;
    }
    ProtoWrapper newMessage = schema.newMessage();
    ProtostuffIOUtil.mergeFrom(bytes, newMessage, schema);
    return newMessage.data;
  }

  private static class ProtoWrapper {
    private Object data;
  }
}
